﻿// 版权所有：
// 文 件  名：MergeSort.cs
// 功能描述：归并排序类
// 创建标识：Seven Song(m.sh.lin0328@163.com) 2014/5/1 
// 修改描述：
//----------------------------------------------------------------*/
using System;
using System.Collections.Generic;

namespace MSL.Utility.Sort
{
    /// <summary>
    /// 快速排序
    /// </summary>
    public class MergeSort : SortBase, ISort
    {
        #region 私有
          /// <summary>
        /// 归并排序（目标数组，子表的起始位置，子表的终止位置）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">数组</param>
        /// <param name="low">开始位置</param>
        /// <param name="mid">中间位置</param>
        /// <param name="high">结束位置</param>
        /// <param name="isAsc">是否升序</param>
        private void SortCore<T>(IList<T> list, int low, int high, bool isAsc) where T : IComparable
        {
            if (low < high)   //子表的长度大于1，则进入下面的递归处理
            {
                int mid = (low + high) / 2;   //子表划分的位置
                SortCore(list, low, mid, isAsc);   //对划分出来的左侧子表进行递归划分
                SortCore(list, mid + 1, high, isAsc);    //对划分出来的右侧子表进行递归划分
                SortCore(list, low, mid, high, isAsc); //对左右子表进行有序的整合（归并排序的核心部分）
            }
        }

        /// <summary>
        /// 归并排序的核心部分：将两个有序的左右子表（以mid区分），合并成一个有序的表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">数组</param>
        /// <param name="low">开始位置</param>
        /// <param name="mid">中间位置</param>
        /// <param name="high">结束位置</param>
        /// <param name="isAsc">是否升序</param>
        private void SortCore<T>(IList<T> list, int low, int mid, int high, bool isAsc) where T : IComparable
        {
            try
            {
                int indexA = low; //左侧子表的起始位置
                int indexB = mid + 1;   //右侧子表的起始位置
                T[] temp = new T[high + 1]; //声明数组（暂存左右子表的所有有序数列）：长度等于左右子表的长度之和。
                int tempIndex = 0;

                while (indexA <= mid && indexB <= high) //进行左右子表的遍历，如果其中有一个子表遍历完，则跳出循环
                {
                    if (isAsc)
                    {
                        temp[tempIndex++] = list[indexA].CompareTo(list[indexB]) <= 0 ? list[indexA++] : list[indexB++];
                    }
                    else
                    {
                        temp[tempIndex++] = list[indexA].CompareTo(list[indexB]) <= 0 ? list[indexB++] : list[indexA++];
                    }
                    //if (list[indexA].CompareTo(list[indexB]) <= 0) //此时左子表的数 <= 右子表的数
                    //{
                    //    temp[tempIndex++] = list[indexA++];    //将左子表的数放入暂存数组中，遍历左子表下标++
                    //}
                    //else//此时左子表的数 > 右子表的数
                    //{
                    //    temp[tempIndex++] = list[indexB++];    //将右子表的数放入暂存数组中，遍历右子表下标++
                    //}
                }
                //有一侧子表遍历完后，跳出循环，将另外一侧子表剩下的数一次放入暂存数组中（有序）
                while (indexA <= mid)
                {
                    temp[tempIndex++] = list[indexA++];
                }
                while (indexB <= high)
                {
                    temp[tempIndex++] = list[indexB++];
                }
                //将暂存数组中有序的数列写入目标数组的制定位置，使进行归并的数组段有序
                tempIndex = 0;
                for (int i = low; i <= high; i++)
                {
                    list[i] = temp[tempIndex++];
                }
            }
            catch (Exception ex)
            { }
        }
        #endregion

        /// <summary>
        /// 倒序排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">集合</param>
        public void Desc<T>(IList<T> list) where T : IComparable
        {
            SortCore(list, 0, list.Count - 1, false);  //不会改变外部引用 参照C#参数传递
        }
        /// <summary>
        /// 升序排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">集合</param>
        public void Asc<T>(IList<T> list) where T : IComparable
        {
            SortCore(list, 0, list.Count - 1, true);
        }
    }
}
